package ling.cfg;


import com.easy.query.core.basic.extension.interceptor.*;
import com.easy.query.core.expression.parser.core.base.WherePredicate;
import com.easy.query.core.expression.sql.builder.EntityInsertExpressionBuilder;
import com.easy.query.core.expression.sql.builder.EntityUpdateExpressionBuilder;
import com.easy.query.core.expression.sql.builder.LambdaEntityExpressionBuilder;
import ling.common.EQueryHelper;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.security.context.PermissionContextHolder;
import ling.common.domain.entity.ICreatedEntity;
import ling.common.domain.entity.IDeptEntity;
import ling.common.domain.entity.IUpdatedEntity;
import lombok.var;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import static com.ruoyi.framework.aspectj.DataScopeAspect.*;

/**
 * ;
 * @author : He-LiangLiang@Outlook.com
 * @date : 2025-2-26
 */

@Aspect
@Component
public class DeptInterceptor implements EntityInterceptor, PredicateFilterInterceptor {
    @Resource
    protected EQueryHelper queryHelper;
    @Override
    public String name() {
        return "DeptInterceptor";
    }

    @Override
    public boolean apply(Class<?> entityClass) {
        return IDeptEntity.class.isAssignableFrom(entityClass)|| ICreatedEntity.IUserId.class.isAssignableFrom(entityClass);
    }

    @Override
    public void configure(Class<?> entityClass, LambdaEntityExpressionBuilder lambdaEntityExpressionBuilder, WherePredicate<Object> sqlWherePredicate) {

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if(attributes==null)
            return;
        HttpServletRequest request = attributes.getRequest();
        var deptIds = (Long[]) request.getAttribute(UserDataScopeContextSign);
        if (deptIds == null)
            return;
        if (deptIds.length == 0) {
            sqlWherePredicate.eq("deptId", 0);
            return;
        }
        var depts = Arrays.stream(deptIds).filter(p -> p > 0).collect(Collectors.toList());
        if (!depts.isEmpty())
            sqlWherePredicate.in("deptId", depts);
        //
        var isUser = Arrays.stream(deptIds).anyMatch(p -> p < 0);
        if (!isUser)
            return;
        var user = SecurityUtils.getLoginUser();
        if (user == null)
            return;
        if (ICreatedEntity.IUserId.class.isAssignableFrom(entityClass))
            sqlWherePredicate.eq("userId", user.getUserId());
        else if (ICreatedEntity.class.isAssignableFrom(entityClass))
            sqlWherePredicate.eq("createdId", user.getUserId());
    }

    @Override
    public void configureInsert(Class<?> entityClass, EntityInsertExpressionBuilder entityInsertExpressionBuilder, Object entity) {
//        if (entity instanceof IDeptEntity) {
//            IDeptEntity deptEntity = (IDeptEntity) entity;
//            var user = SecurityUtils.getLoginUser();
//
//            if (deptEntity.getDeptId() == null && user != null) {
//                deptEntity.setDeptId(user.getDeptId());
//            }
//        }
        if(entity instanceof  ICreatedEntity) {
            var tmp = (ICreatedEntity) entity;

            if (tmp.getCreatedId() == null) {
                var pr= SecurityUtils.getAuthentication().getPrincipal();
                if(pr instanceof  LoginUser){
                    var user = (LoginUser)pr;
                    tmp.setCreatedId(user.getUserId());
                }
            }
            if (tmp.getCreatedTime() == null)
                tmp.setCreatedTime(new Date());
        }
    }

    @Override
    public void configureUpdate(Class<?> entityClass, EntityUpdateExpressionBuilder entityUpdateExpressionBuilder, Object entity) {
        if (entity instanceof IUpdatedEntity) {
            var tmp = (IUpdatedEntity) entity;
            tmp.setUpdatedTime(new Date());
            var user = SecurityUtils.getLoginUser();
            if (user != null)
                tmp.setUpdatedId(user.getUserId());
        }
    }

    @Before("@annotation(controllerDataScope)")
    public void doBefore(JoinPoint joinPoint, DataScope controllerDataScope) throws Throwable {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (StringUtils.isNull(loginUser))
            return;
        SysUser currentUser = loginUser.getUser();
        // 如果是超级管理员，则不过滤数据
        if (StringUtils.isNull(currentUser) || currentUser.isAdmin())
            return;
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        String permission = StringUtils.defaultIfEmpty(controllerDataScope.permission(), PermissionContextHolder.getContext());
        var dlist = dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(),
                controllerDataScope.userAlias(), permission);

        if (dlist != null)
            request.setAttribute(UserDataScopeContextSign, dlist.toArray(new Long[0]));
    }
    public static final String UserDataScopeContextSign="__User_Data_Scope_Dept";
    public  List<Long> dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias, String permission)
    {
        StringBuilder sqlString = new StringBuilder();
        return scopeDeptIds(user, permission);

    }

    private ArrayList<Long> scopeDeptIds(SysUser user, String permission) {
        List<String> conditions = new ArrayList<String>();
        var scopeCustomIds = new ArrayList<Long>();
        user.getRoles().forEach(role -> {
            if (DATA_SCOPE_CUSTOM.equals(role.getDataScope()) && StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
            {
                scopeCustomIds.add(role.getRoleId());
            }
        });
        var dlist=new ArrayList<Long>();//部门id,-1代表用户
        for (SysRole role : user.getRoles())
        {
            String dataScope = role.getDataScope();
            if (conditions.contains(dataScope))
            {
                continue;
            }
//            if (!StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
//            {
//                continue;
//            }
            if (DATA_SCOPE_ALL.equals(dataScope))
            {
                dlist=null;
                break;
            }
            else if (DATA_SCOPE_CUSTOM.equals(dataScope))
            {

                if (scopeCustomIds.size() > 1)
                {
                    var deptIds=queryHelper.CreateItems("SELECT dept_id FROM sys_role_dept WHERE ")
                            .in("role_id",scopeCustomIds)
                            .resultPkg().sqlQuery(Long.class);
                    dlist.addAll(deptIds);
                }
                else
                {
                    var deptIds=queryHelper.CreateItems("SELECT dept_id FROM sys_role_dept WHERE ")
                            .addItem(" role_id=?",role.getRoleId())
                            .resultPkg().sqlQuery(Long.class);
                    dlist.addAll(deptIds);
                }
            }
            else if (DATA_SCOPE_DEPT.equals(dataScope))
            {
                dlist.add( user.getDeptId());
            }
            else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) {
                var deptIds = queryHelper.CreateItems("SELECT dept_id FROM sys_dept WHERE ")
                        .addItem(" dept_id=?", user.getDeptId())
                        .addItem(" or")
                        .addItem(" find_in_set(?, ancestors )", user.getDeptId())
                        .resultPkg().sqlQuery(Long.class);
                dlist.addAll(deptIds);
            }
            else if (DATA_SCOPE_SELF.equals(dataScope))
            {
                dlist.add( -user.getUserId());
            }
            conditions.add(dataScope);
        }
        return dlist;
    }

   public  ArrayList<Long> scopeDeptIds(SysUser user) {
        List<String> conditions = new ArrayList<String>();
        var scopeCustomIds = new ArrayList<Long>();
        user.getRoles().forEach(role -> {
            if (DATA_SCOPE_CUSTOM.equals(role.getDataScope()))
            {
                scopeCustomIds.add(role.getRoleId());
            }
        });
        var dlist=new ArrayList<Long>();//部门id,-1代表用户
        for (SysRole role : user.getRoles())
        {
            String dataScope = role.getDataScope();
            if (conditions.contains(dataScope))
            {
                continue;
            }
            if (DATA_SCOPE_ALL.equals(dataScope))
            {
                dlist=null;
                break;
            }
            else if (DATA_SCOPE_CUSTOM.equals(dataScope))
            {

                if (scopeCustomIds.size() > 1)
                {
                    var deptIds=queryHelper.CreateItems("SELECT dept_id FROM sys_role_dept WHERE ")
                            .in("role_id",scopeCustomIds)
                            .resultPkg().sqlQuery(Long.class);
                    dlist.addAll(deptIds);
                }
                else
                {
                    var deptIds=queryHelper.CreateItems("SELECT dept_id FROM sys_role_dept WHERE ")
                            .addItem(" role_id=?",role.getRoleId())
                            .resultPkg().sqlQuery(Long.class);
                    dlist.addAll(deptIds);
                }
            }
            else if (DATA_SCOPE_DEPT.equals(dataScope))
            {
                dlist.add( user.getDeptId());
            }
            else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) {
                var deptIds = queryHelper.CreateItems("SELECT dept_id FROM sys_dept WHERE ")
                        .addItem(" dept_id=?", user.getDeptId())
                        .addItem(" or")
                        .addItem(" find_in_set(?, ancestors )", user.getDeptId())
                        .resultPkg().sqlQuery(Long.class);
                dlist.addAll(deptIds);
            }
            else if (DATA_SCOPE_SELF.equals(dataScope))
            {
                dlist.add( -user.getUserId());
            }
            conditions.add(dataScope);
        }
        return dlist;
    }
}

